package com.qyer.search.servlet;

import static com.qyer.commons.http.ErrorHttpResult.createErrorResult;
import static com.qyer.search.Constants.PROJECT_NAME;
import static com.qyer.search.Constants.PROJECT_NAMESPACE;
import static com.qyer.search.model.result.MetaNormalHttpResult.createMetaNormalResult;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.qyer.commons.http.HttpResult;
import com.qyer.log.ErrorLogger;
import com.qyer.search.enums.SearchError;
import com.qyer.search.exception.SearchException;
import com.qyer.search.model.SearchParameter;
import com.qyer.search.model.SearchParameterEntity;
import com.qyer.search.model.SearchParameterOrigin;
import com.qyer.search.model.result.FilterNormalHttpResult;
import com.qyer.search.model.result.SearchFilterInfo;
import com.qyer.search.model.result.SearchMetaInfo;
import com.qyer.search.utils.JsonOperator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * User: Z J Wu Date: 2016/01/05 Time: 16:09 Package: com.qyer.search.servlet
 */
public abstract class AbstractServlet extends HttpServlet {

  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServlet.class);

  protected void checkParam(SearchParameter searchParameter) throws SearchException {
    if (StringUtils.isEmpty(searchParameter.getContext())) {
      throw new SearchException("context is null");
    }
  }

  protected void checkParam(SearchParameterOrigin searchParameter) throws SearchException {
    if (StringUtils.isEmpty(searchParameter.getContext())) {
      throw new SearchException("context is null");
    }
  }

  protected void checkParam(SearchParameterEntity searchParameter) throws SearchException {
    if (StringUtils.isEmpty(searchParameter.getContext())) {
      throw new SearchException("context is null");
    }
  }

  protected int timeUse(long t1) {
    return (int) (System.currentTimeMillis() - t1);
  }

  protected HttpResult buildError(String requestId, SearchError error, Exception e,
                                  String myMessage, long requestBeginTime) {
    StringBuilder sb = new StringBuilder();
    if (StringUtils.isNotEmpty(myMessage)) {
      sb.append('(');
      sb.append(myMessage);
      sb.append(") - ");
    }
    if (e != null) {
      String exceptionMessage = e.getMessage();
      if (StringUtils.isEmpty(exceptionMessage)) {
        sb.append(e.toString());
      } else {
        sb.append(exceptionMessage);
      }
    }
    return createErrorResult(PROJECT_NAME, PROJECT_NAMESPACE, requestId, timeUse(requestBeginTime),
                             error.getErrorCode(), sb.toString());
  }

  protected HttpResult buildOK(long requestBeginTime, String requestId, String strategy,
                               Object data, SearchMetaInfo meta) {
    return createMetaNormalResult(PROJECT_NAME, PROJECT_NAMESPACE, requestId, strategy,
                                  timeUse(requestBeginTime), data, meta);
  }

  protected HttpResult buildOK(long requestBeginTime, String requestId, String strategy,
                               Object data, SearchFilterInfo meta) {
    return FilterNormalHttpResult.createMetaNormalResult(PROJECT_NAME, PROJECT_NAMESPACE, requestId,
                                                         strategy, timeUse(requestBeginTime), data,
                                                         meta);
  }

  protected void writeOK(HttpServletResponse response, long requestBeginTime, String requestId,
                         String strategy, Object data, SearchMetaInfo meta) {
    HttpResult hr = buildOK(requestBeginTime, requestId, strategy, data, meta);
    try {
      write(response, JsonOperator.getInstance().toJson(hr));
    } catch (IOException e) {
      LOGGER.error("Cannot write json", e);
    }
  }

  protected void writeOK(HttpServletResponse response, long requestBeginTime, String requestId,
                         String strategy, Object data, SearchFilterInfo meta) {
    HttpResult hr = buildOK(requestBeginTime, requestId, strategy, data, meta);
    try {
      write(response, JsonOperator.getInstance().toJson(hr));
    } catch (IOException e) {
      LOGGER.error("Cannot write json", e);
    }
  }

  protected void writeError(SearchParameter searchParameter, HttpServletResponse response,
                            long requestBeginTime, SearchError error, Exception e) throws
    JsonProcessingException {
    ErrorLogger.logError(searchParameter, e);
    HttpResult hr = buildError(searchParameter.getRequestId(), error, e, null, requestBeginTime);
    try {
      write(response, JsonOperator.getInstance().toJson(hr));
    } catch (IOException e2) {
      e2.printStackTrace();
    }
  }

  protected void writeError(SearchParameterOrigin searchParameter, HttpServletResponse response,
                            long requestBeginTime, SearchError error, Exception e) throws
    JsonProcessingException {

    ErrorLogger.logError(searchParameter, e);
    HttpResult hr = buildError(searchParameter.getRequestId(), error, e, null, requestBeginTime);
    try {
      write(response, JsonOperator.getInstance().toJson(hr));
    } catch (IOException e2) {
      e2.printStackTrace();
    }
  }

  public void writeError(String requestId, String context, Map<String, Object> conditions, HttpServletResponse response,
                            long requestBeginTime, SearchError error, Exception e) throws
    JsonProcessingException {

    ErrorLogger.logError(requestId, context, conditions, e);
    HttpResult hr = buildError(requestId, error, e, null, requestBeginTime);
    try {
      write(response, JsonOperator.getInstance().toJson(hr));
    } catch (IOException e2) {
      e2.printStackTrace();
    }
  }

  protected void write(HttpServletResponse response, String s) throws IOException {
    PrintWriter pw = response.getWriter();
    pw.write(s);
    pw.flush();
  }
}
